package org.acmclass.fatworm.test.result;

import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.acmclass.fatworm.test.FatTestException;
import org.acmclass.fatworm.test.sql.SQLWithOptions;

public abstract class ResultConsumer {

	protected Map<Integer, ResultSetMetaData> metadatas = Collections
			.synchronizedMap(new HashMap<Integer, ResultSetMetaData>());
	protected Map<Integer, SQLWithOptions> sqls = Collections
			.synchronizedMap(new HashMap<Integer, SQLWithOptions>());

	public void setResultSetMetaData(int threadID, ResultSetMetaData metadata) {
		metadatas.put(threadID, metadata);
	}

	public void setSQL(int threadID, SQLWithOptions sql) {
		sqls.put(threadID, sql);
	}

	public void process(int threadID, Map<Integer, Object> row)
			throws SQLException {
		int columnCount;
		columnCount = metadatas.get(threadID).getColumnCount();
		StringBuilder resultLine = new StringBuilder();
		for (int i = 1; i <= columnCount; ++i) {
			resultLine.append(format(metadatas.get(threadID).getColumnType(i),
					row.get(i)));
			if (i < columnCount)
				resultLine.append("\t");
		}
		processLineString(threadID, resultLine.toString());
	}

	protected abstract void processLineString(int threadID, String resultLine);

	public abstract void processQueryFinal(int threadID) throws SQLException;

	public abstract void close() throws FatTestException;

	public abstract String getResult();

	protected String format(int type, Object value) throws SQLException {
		if (value == null) {
			return "NULL";
		}
		switch (type) {
		case java.sql.Types.BOOLEAN:
		case java.sql.Types.CHAR:
		case java.sql.Types.VARCHAR:
		case java.sql.Types.DATE:
		case java.sql.Types.TIMESTAMP:
		case java.sql.Types.INTEGER:
			return value.toString();
		case java.sql.Types.FLOAT:
		case java.sql.Types.DECIMAL:
			return String.format("%.5g", value);
		}
		throw new SQLException("unknown column type " + type);
	}

}
